package net.lab0.fractal.abstracts;


import javax.swing.SwingUtilities;
import javax.swing.event.EventListenerList;

import net.lab0.fractal.classes.ViewCoordinates;
import net.lab0.fractal.event.IterationsChangedEvent;
import net.lab0.fractal.event.IterationsChangedListener;
import net.lab0.fractal.event.ProgressEvent;
import net.lab0.fractal.event.ProgressListener;


/**
 * @author 116
 */
public abstract class AbstractUI2DFractal
implements AbstractUI2DFractalInterface
{
	private ViewCoordinates		viewCoordinates;
	protected long				maxIteration;
	protected float				progressUpdateInterval;
	protected long				timeUpdateInterval;
	
	private float				progress					= 0f;
	private float				lastNotifiedProgress		= 0f;
	private long				lastNotifiedProgressTime	= System.currentTimeMillis();
	private EventListenerList	eventListenerList			= new EventListenerList();
	
	public AbstractUI2DFractal(ViewCoordinates viewCoordinates, long maxIteration, float progressUpdateInterval, long timeUpdateInterval)
	{
		super();
		this.viewCoordinates = viewCoordinates;
		this.maxIteration = maxIteration;
		this.progressUpdateInterval = progressUpdateInterval;
		this.timeUpdateInterval = timeUpdateInterval;
	}
	
//	@Override
//	public void addZoom(double quantity)
//	{
//		zoomLevel += quantity;
//	}
//	
//	@Override
//	public void setZoom(double zoomLevel)
//	{
//		this.zoomLevel = zoomLevel;
//	}
//	
//	@Override
//	public double getZoom()
//	{
//		return zoomLevel;
//	}
	
	@Override
	public ViewCoordinates getViewCoordinates()
	{
		return viewCoordinates;
	}
	
	protected void fireProgressEvent(boolean finished)
	{
		final ProgressEvent event = new ProgressEvent(this, progress, finished);
//		System.out.println(progress + " / " + finished);
		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				for (ProgressListener l : eventListenerList.getListeners(ProgressListener.class))
				{
					l.progression(event);
				}
			}
		});
	}
	
	protected void fireIterationsChangedEvent()
	{
		IterationsChangedEvent event = new IterationsChangedEvent(this, maxIteration);
		for (IterationsChangedListener l : eventListenerList.getListeners(IterationsChangedListener.class))
		{
			l.iterationsChanged(event);
		}
	}
	
	@Override
	public float getProgress()
	{
		return progress;
	}
	
	protected void setProgress(float progress)
	{
		this.progress = progress;
//		System.out.println(progress);
//		System.out.println(lastNotifiedProgress);
//		System.out.println(lastNotifiedProgressTime);
		if (progress > lastNotifiedProgress + progressUpdateInterval && System.currentTimeMillis() > lastNotifiedProgressTime + timeUpdateInterval
		|| progress < lastNotifiedProgress)
		{
			lastNotifiedProgress = progress;
			lastNotifiedProgressTime = System.currentTimeMillis();
			fireProgressEvent(false);
		}
	}
	
	public void addProgressListener(ProgressListener listener)
	{
		eventListenerList.add(ProgressListener.class, listener);
	}
	
	@Override
	public void setMinimumProgressUpdateInterval(float step)
	{
		this.progressUpdateInterval = step;
	}
	
	@Override
	public void setMinimumTimeUpdateInterval(long step)
	{
		this.timeUpdateInterval = step;
	}
	
	@Override
	public long getMaxIteration()
	{
		return maxIteration;
	}
	
	@Override
	public void setMaxIteration(long maxIteration)
	{
		if (maxIteration > 0)
		{
			this.maxIteration = maxIteration;
			fireIterationsChangedEvent();
		}
	}
	
//	@Override
//	public void setZoomStep(double zoomStep)
//	{
//		this.zoomStep = zoomStep;
//	}
//	
//	@Override
//	public double getZoomStep()
//	{
//		return zoomStep;
//	}
}
